/*
* Copyright (C) 2020 ~ 2023 chaigec All Rights Reserved.
*
* Author:     chaigec <chaigec@163.com>
* Maintainer: chaigec <chaigec@163.com>

 * Use of this source code is governed by MIT license that can be found in the
 * LICENSE file in the root of the source tree. All contributing project authors
 * may be found in the AUTHORS file in the root of the source tree.
*/

#ifndef MK_GB_SERVER_H
#define MK_GB_SERVER_H
#include <MkHttpApi/MkHttpApi.h>
#include <MkGb28181/MkGb28181.h>
#include <MkUtil/MkPtzCommand.h>
#include <MkUtil/MkUtil.h>
#include <MkUtil/MkIni.h>
#include <tinyxml2.h>

typedef enum _mk_gb_server_error
{
    MediaServerNotOnline = ErrorCodeUser + 1,
}MkGbServerErrorCode;

class CMkHttpHooker;
class CMkGbServer : public CMkHttpApi
{
    typedef enum _notify_message_type
    {
        MkNotifyActionAlarm,
        MkNotifyActionDeviceOnline,
        MkNotifyActionCatalog,
        MkNotifyActionPlayEnd,
        MkNotifyActionPlayInfo,
        MkNotifyActionEnd
    }MkNotifyMessageType;

    using GbParser = Uint32(CMkGbServer::*)(const Json::Value& JsonReq, const MkMap<MkString, MkString>& MapQuery, const MkHttpResponseJsonCb& ResCb);
    typedef MkUnorderedMap<MkString, GbParser>   MapParser;

    typedef struct _online_device_param
    {
        MkString                            DeviceId;
        MkString                            DevHost;
        Uint16                              DevPort;
        CMkTime                             LastKeepAliveTime;
        MkString                            CheckTimer;
        MkString                            RegisterId;
        Uint32                              HBInterval;  //heat beat interval
        Uint32                              HBCount;     //heat beat count

        _online_device_param()
        {
            CMkUtil::CreateRandomString(Len16, CheckTimer);
            HBCount = 3;
            HBInterval = 60;
        }
    }MkOnlineDevice;

    typedef struct _up_gb_server
    {
        MkString                            GbSvrId;
        MkString                            GbSvrRealm;
        MkString                            GbSvrHost;
        Uint16                              GbSvrPort;
        Uint32                              HBInterval;  //heat beat interval
        Uint32                              HBCount;     //heat beat count
        Uint32                              Expires;
        BOOL                                bTcp;

        BOOL                                bOnline;
        MkString                            RegisterDelayer;
        MkString                            KeepAliverTimer;
        CMkTime                             LastKeepAliveTime;
        MkMapString                         MapUpMobilePositionSubscirbe;  //key channel id  value subscribe id
        MkMapString                         MapUpPtzPositionSubscribe;    //key channel id value subscribe id
        MkString                            CatalogSubscribeId;
        _up_gb_server()
        {
            Expires = 3600;
            bTcp = FALSE;
            bOnline = FALSE;
            CMkUtil::CreateRandomString(Len16, RegisterDelayer);
            CMkUtil::CreateRandomString(Len16, KeepAliverTimer);
        }
    }MkUpGbServer;

    typedef struct _play_param
    {
        MkString        MediaServerId;
        MkString        MediaPath;      //subject source 
        MkString        ToMediaServerSession;
        MkString        ToChannelSession;
        BOOL            bPlaying;
    }MkGbPlayParam;

    typedef struct _decoder_param
    {
        MkString        MediaServerId;
        MkString        MediaPath;
        MkString        DecoderChannelId;
        MkString        DecoderDeviceId;
        MkString        ToDecoderSession;
        MkString        ToMediaServerSession;
    }MkGbDecoderParam;
public:
    CMkGbServer(CMkEventPool* pEventPool, CMkTimer* pTimer);
    ~CMkGbServer();
    Uint32 Init(int argc, char** argv);
protected:
private:
    Uint32 Start();
    Uint32 Stop();
    Uint32 ReadConfig();
    Uint32 WriteUpSvrJson();
    Uint32 GetVersion(MkString& Version);
    Uint32 AddParser(const MkString& Path, const MkHttpMethod& Method, const GbParser& Parser);
    Uint32 RegisterAllUpServer();
private:
    Uint32 OnGbRequest(const CMkGbRequest* pGbReq, const MkGbResponseCallback& Cb);
    Uint32 OnGbDeviceAuthor(const CMkGbRequest* pGbReq, const MkGbResponseCallback& Cb);
    Uint32 OnGbMessageRequest(const CMkGbMessageRequest* pGbReq, const MkGbResponseCallback& Cb);
    Uint32 OnGbNotifyReqeust(const CMkGbNotifyRequest* pGbReq, const MkGbResponseCallback& Cb);
    Uint32 OnGbSubscribeRequest(const CMkGbSubscribeRequest* pGbReq, const MkGbResponseCallback& Cb);
    Uint32 OnGbInviteRequest(const CMkGbInviteReqeust* pGbReq, const MkGbResponseCallback& Cb);
    Uint32 OnGbByeRequest(const CMkGbByeReqeust* pGbReq, const MkGbResponseCallback& Cb);
    Uint32 OnGbDeviceKeepAlive(const CMkGbMessageRequest* pGbReq, const MkGbResponseCallback& Cb);

private:
    Uint32 OnDeviceCheckTimer();
private:
    Uint32 OnRequestJsonParse(const MkHttpMethod& Method, const MkString& Path, const MkMap<MkString, MkString>& MapQuery, const Json::Value& JsonReq, const MkHttpResponseJsonCb& cb) override;
    Uint32 OnWebSockekAccessed(CMkHttpSession* pSession) override;

    Uint32 GetVersionParse(const Json::Value& JsonReq, const MkMap<MkString, MkString>& MapQuery, const MkHttpResponseJsonCb& ResCb);
    Uint32 GetWebSocketAccessKeyParse(const Json::Value& JsonReq, const MkMap<MkString, MkString>& MapQuery, const MkHttpResponseJsonCb& ResCb);

    Uint32 GetConfigParse(const Json::Value& JsonReq, const MkMap<MkString, MkString>& MapQuery, const MkHttpResponseJsonCb& ResCb);
    Uint32 ChangeConfigParse(const Json::Value& JsonReq, const MkMap<MkString, MkString>& MapQuery, const MkHttpResponseJsonCb& ResCb);

    Uint32 GetHttpHookerParse(const Json::Value& JsonReq, const MkMap<MkString, MkString>& MapQuery, const MkHttpResponseJsonCb& ResCb);
    Uint32 ChangeHttpHookerParse(const Json::Value& JsonReq, const MkMap<MkString, MkString>& MapQuery, const MkHttpResponseJsonCb& ResCb);

    Uint32 GetOnlineDeviceParse(const Json::Value& JsonReq, const MkMap<MkString, MkString>& MapQuery, const MkHttpResponseJsonCb& ResCb);
    Uint32 StartPlayParse(const Json::Value& JsonReq, const MkMap<MkString, MkString>& MapQuery, const MkHttpResponseJsonCb& ResCb);
    Uint32 StopPlayParse(const Json::Value& JsonReq, const MkMap<MkString, MkString>& MapQuery, const MkHttpResponseJsonCb& ResCb);
    Uint32 PlayControlParse(const Json::Value& JsonReq, const MkMap<MkString, MkString>& MapQuery, const MkHttpResponseJsonCb& ResCb);

    Uint32 StartDecodeParse(const Json::Value& JsonReq, const MkMap<MkString, MkString>& MapQuery, const MkHttpResponseJsonCb& ResCb);
    Uint32 StopDecodeParse(const Json::Value& JsonReq, const MkMap<MkString, MkString>& MapQuery, const MkHttpResponseJsonCb& ResCb);

    Uint32 DeviceQueryParse(const Json::Value& JsonReq, const MkMap<MkString, MkString>& MapQuery, const MkHttpResponseJsonCb& ResCb);
    Uint32 DeviceConfigParse(const Json::Value& JsonReq, const MkMap<MkString, MkString>& MapQuery, const MkHttpResponseJsonCb& ResCb);
    Uint32 DeviceControlParse(const Json::Value& JsonReq, const MkMap<MkString, MkString>& MapQuery, const MkHttpResponseJsonCb& ResCb);

    Uint32 CatalogChangeParse(const Json::Value& JsonReq, const MkMap<MkString, MkString>& MapQuery, const MkHttpResponseJsonCb& ResCb);

    Uint32 AddUpServerParse(const Json::Value& JsonReq, const MkMap<MkString, MkString>& MapQuery, const MkHttpResponseJsonCb& ResCb);
    Uint32 GetUpServerParse(const Json::Value& JsonReq, const MkMap<MkString, MkString>& MapQuery, const MkHttpResponseJsonCb& ResCb);
    Uint32 DeleteUpServerParse(const Json::Value& JsonReq, const MkMap<MkString, MkString>& MapQuery, const MkHttpResponseJsonCb& ResCb);
private:
    Uint32 DefaultCallbackParse(const Json::Value& JsonReq, const MkMap<MkString, MkString>& MapQuery, const MkHttpResponseJsonCb& ResCb);
private:  //web socket notify messages
    Uint32 NotifyMsg(const MkNotifyMessageType& ActionType, const Json::Value& Body, CMkHttpSession* pSession = nullptr);
    Uint32 NotifyMsg(const MkString& strAction, const Json::Value& Body, CMkHttpSession* pSession = nullptr);
    Uint32 NotifyCatalog(const MkString& DeviceId, const MkVector<MkMapString>& VecCatalog, CMkHttpSession* pSession = nullptr);
    Uint32 NotifyDeviceOnline(const MkString& DeviceId, BOOL bOnline, CMkHttpSession* pSession = nullptr);
    Uint32 NotifyUpServerOnline(const MkString& DeviceId, BOOL bOnline, CMkHttpSession* pSession = nullptr);
    Uint32 NotifyPlayEnd(const MkString& MediaPath, CMkHttpSession* pSession = nullptr);
    Uint32 NotifyPlayInfo(CMkHttpSession* pSession = nullptr);

private: //third http callback messages
    Uint32 DeviceAuthorRequest(const CMkGbDeviceAuthorRequest& Req, const MkHttpResponseJsonCb& ResCb);
    Uint32 UpServerRegisterRequest(const MkString& ServerId, const MkString& Realm, const MkString& Nonce, const MkString& Uri, const MkString& Algorithm, const MkHttpResponseJsonCb& ResCb);
    Uint32 CatalogRequest(const MkHttpResponseJsonCb& ResCb);
    Uint32 RealplayRequest(const MkString& DeviceId, const MkString& ChannelId, const MkString& UpRtpHost, Uint16 UpRtpPort, Uint32 UpRtpSsrc, const MkHttpResponseJsonCb& ResCb);
private:
    Uint32 AddOnlineDevice(const MkString& RegisterId, const MkString& DeviceId, const MkString& DevIp, Uint16 DevPort);
    Uint32 UpdateMapCatalog(const MkString& DeviceId, const MkVector<MkMapString>& VecCatalog);
    Uint32 DeleteOnlineDevice(const MkString& DeviceId);
    Uint32 GetDeviceBasicConfig(const MkString& DeviceId);
    MkString GetFreeMediaServer();

    Uint32 AddMapDeviceChild(const MkString& ChildId, const MkString& DeviceId);
    Uint32 GetDevice(const MkString& ChildId, MkString& DeviceId);
    Uint32 DeleteDeviceChildFromDevice(const MkString& DeviceId);
    Uint32 DeleteDeviceChild(const MkString& ChildId);

    Uint32 RegisterUpServer(const CMkGbDeviceAuthorRequest& Req, BOOL bFailEnd = FALSE);
    Uint32 NotifyKeepAliveUpServer(const MkString& SvrId);
    Uint32 NotifyDeviceNotifyAllUpServer(const CMkGbMessageRequest* pGbReq);

    Uint32 DeviceAuthorSuccess(const MkString& RegisterId, const MkString& DeviceId, const MkString& DeviceHost, Uint16 DevicePort, BOOL bOnline);

    //Uint32 PacketDeviceConfigToJson(const CMkGbResponse* pResponse, Json::Value& JsonConfig);
    MkString GetRequestStringValue(const Json::Value& JsonReq, const MkMap<MkString, MkString>& MapQuery, const MkString& strKey);
    Uint32 GetRequestUint32Value(const Json::Value& JsonReq, const MkMap<MkString, MkString>& MapQuery, const MkString& strKey);
    float GetRequestFloatValue(const Json::Value& JsonReq, const MkMap<MkString, MkString>& MapQuery, const MkString& strKey);
    double GetRequestDoubleValue(const Json::Value& JsonReq, const MkMap<MkString, MkString>& MapQuery, const MkString& strKey);
    BOOL GetRequestBoolValue(const Json::Value& JsonReq, const MkMap<MkString, MkString>& MapQuery, const MkString& strKey);

    Uint32 GetNotifyAction(const MkNotifyMessageType& ActionType, MkString& strType);
    Uint32 GetMkNofiyActionType(const MkString& StrType, MkNotifyMessageType& ActionType);
    Uint32 ParseJsonContentToMapParam(const Json::Value& JsonParam, MkMapString& MapParam);
    Uint32 ParseJsonContentToInfoParam(const Json::Value& JsonParam, MkPair<MkString, MkString>& InfoParam);
    Uint32 ParseJsonContentToGbMessage(const Json::Value& JsonContent, MkGbMessage& Message);
    Uint32 PacketMapParamToJson(const MkMapString& MapParam, Json::Value& JsonContent);
    Uint32 PacketGbMessageToJson(const MkGbMessage& Message, Json::Value& JsonContent);
    Uint32 MapParamToGbPtzCmd(const MkMapString& MapParam, MkString& GbPtzCmd);
    Uint32 MkPtzCmdToGbPtzCmd(const MkPtzCommand& PtzCmd, MkGbPtzCommandType& GbPtzCmd);
    Uint32 ResponseHttp(const MkHttpResponseJsonCb& ResCb, Uint32 ErrorCode, const CMkGbResponse* pResponse);
private:  //play functions
    Uint32 PlayStream(const MkString &RouterId, const MkString& ChannelId, const CMkTime& BeginTime, const CMkTime& EndTime, const MkString& PlayType, const MkHttpResponseJsonCb& ResCb);
    Uint32 DeletePlay(const MkString& MediaPath);
    Uint32 GetPlayInfo(const MkString& MediaPath, MkGbPlayParam& Param);
    Uint32 DeletePlayFromMediaServer(const MkString& MediaServerId);
    Uint32 UpdatePlayParam(const MkString& MediaPath, const MkString& ToChannelSession, const MkString& ToMediaServerSession);
private:
    CMkIni                            m_ConfigIni;
    MkUnorderedMap<MkString, MkGbPlayControlType> m_MapPlayControl;
    MkUnorderedMap<Uint32, MkString>  m_MapNotifyMsgType;
    BOOL                              m_bReboot;
    CMkHttpHooker*                    m_pHttpHooker;
    CMkGb28181*                       m_pGb28181;
    //config offset times
    Uint32                            m_RegisterDelaySec;  // re register when register failed

    MapParser                         m_MapGetParser;
    MapParser                         m_MapPutParser;
    MapParser                         m_MapPostParser;
    MapParser                         m_MapDeleteParser;

    CMkRwLock                         m_OnlineDeviceLock;
    MkMap<MkString, MkOnlineDevice>   m_MapOnlineDevice;
    MkString                          m_DeviceCheckTimer;

    CMkRwLock                         m_MediaServerLock;
    MkMap<MkString, Uint32>           m_MapMediaServer;       //key media server id  value score  max maxint32

    CMkRwLock                         m_PlayLock;
    MkMap<MkString, MkGbPlayParam>    m_MapPlay;            //key subject source

    CMkRwLock                         m_DecoderLock;
    MkMap<MkString, MkGbDecoderParam> m_MapDecoder;         //key to decoder session

    CMkRwLock                         m_UpPlayLock;
    MkMapString                       m_MapUpPlay;

    CMkRwLock                         m_DeviceChildLock;
    //key device child alarm id,or channel id,audio id  value parent id 
    MkMapString                       m_MapDeviceChild;



    MkString                          m_TalkSourceId;

    CMkLock                                 m_QueryLock;
    MkMap<MkString, MkVector<MkGbMessage>>  m_QueryResult;  //key dstid+query type

    CMkLock                                 m_GetPresetLock;
    MkMap<MkString, MkGbVectorPreset>       m_MapPresetResult;

    CMkRwLock                               m_GbServerLock;
    MkMap<MkString, MkUpGbServer>           m_MapUpGbServer;        //key up server id
};





#endif
